#!/usr/bin/env python
#
# Test proggy to dick around with the DBus and NetworkManager
#

import dbus
import uuid

def main():

    bus = dbus.SystemBus()
    service_name = "org.freedesktop.NetworkManager"
    devices = dbus.Array()
    
    devices = GetDevices(service_name)
    
    #print "\n\nDevices:"
    #print devices
    lendev = len(devices)
    #print lendev

    # Find the wifi devices
    # Returns a dict, with the interface as the key and the NM path as the value
    wifi_devices = ShowWifiDevices(service_name, devices)

    #print len(wifi_devices)
    for k in wifi_devices:
        interface = str(k)
        print interface
    #print wifi_devices.keys()

    # Default to wlan0
    
    # wifi_dev = dict()
    wifi_dev = GetWifiDevice(service_name, devices)
    
    
    # Now let's work on the wifi device (assuming there's only 1, for now)
    print "\nThe Wifi device is:"
    print wifi_dev

    # Proxy the wifi object
    #wifi_proxy = bus.get_object(service_name,wifi_dev['device'])
    wifi_proxy = bus.get_object(service_name,wifi_devices['wlan0'])
    #print wifi_dev['device']

    # Create an interface with the object proxy
    wifi_iface = dbus.Interface(wifi_proxy, "org.freedesktop.NetworkManager.Device.Wireless")
    # Create an interface for the properties of the wifi object
    wifi_prop_iface = dbus.Interface(wifi_proxy, "org.freedesktop.DBus.Properties")

    # Get all properties first
    wifi_properties = wifi_prop_iface.GetAll("org.freedesktop.NetworkManager.Device.Wireless")
    
    for wp in wifi_properties:
        datum = str(wp) + ':\t\t' + str(wifi_properties[wp])
        print datum

    # Get the active access point
    connected = ShowActiveAccessPoint(service_name, wifi_properties['ActiveAccessPoint'])
    
    if connected == 0:
        print "Not connected to any Access Point"
    else:
        print "Connected"

    # Now, we want to display the available Access Points
    aps = wifi_iface.GetAccessPoints()

    PrintAccessPoints(service_name, aps)

    DisconnectAccessPoint(service_name, wifi_devices['wlan0'])

    print "Freaky ninja chun!"


def GetDevices(service_name):
    
    bus = dbus.SystemBus()
    # Get a proxy for the NetworkManager object
    proxy = bus.get_object(service_name, "/org/freedesktop/NetworkManager")
    
    # It does look a bit f'ed up, doesn't it? Yes, it does.
    manager = dbus.Interface(proxy, "org.freedesktop.NetworkManager")
    
    # Let's get the devices that are available
    devices = manager.GetDevices()

    return devices

def ShowWifiDevices(service_name, devices):

    wifi_devices = dict()

    bus = dbus.SystemBus()

    for d in devices:
        dev_proxy = bus.get_object(service_name, d)
        prop_iface = dbus.Interface(dev_proxy, "org.freedesktop.DBus.Properties")

        # Just get all the properties, and sort it out later
        properties = prop_iface.GetAll("org.freedesktop.NetworkManager.Device")

        # Get the wifi
        if properties['DeviceType'] == 2:
            interface = properties['Interface']
            wifi_devices[interface] = d

    return wifi_devices

def GetWifiDevice(service_name, devices):

    bus = dbus.SystemBus()

    wifi_dev = dbus.Dictionary()

#    print "The devices available are:"
    for d in devices:
#        print d
        # Now find out the name of the devices
        dev_proxy = bus.get_object(service_name, d)
        prop_iface = dbus.Interface(dev_proxy, "org.freedesktop.DBus.Properties")
        
        # We should now have a dict of all the properties for the device
        properties = prop_iface.GetAll("org.freedesktop.NetworkManager.Device")
        
        # Print out the properties
        for p in properties:
            datum = str(p) + ":\t" + str(properties[p])
 #           print datum
            
        # Remember which interface is the wi-fi one
        if properties['DeviceType'] == 2:
            wifi_dev['device'] = str(d)
            wifi_dev['interface'] = str(properties['Interface'])
        else:
            pass
    
    return wifi_dev

def PrintAccessPoints(service_name, aps):

    bus = dbus.SystemBus()
    # And we want to print the bargers out
    for path in aps:
        acc_proxy = bus.get_object(service_name, path)
        acc_iface = dbus.Interface(acc_proxy, "org.freedesktop.NetworkManager.AccessPoint")
        acc_prop_iface = dbus.Interface(acc_proxy, "org.freedesktop.DBus.Properties")
        acc_ssid = acc_prop_iface.Get("org.freedesktop.NetworkManager.AccessPoint", "Ssid", byte_arrays=True)
        acc_strength = acc_prop_iface.Get("org.freedesktop.NetworkManager.AccessPoint", "Strength", byte_arrays=True)
        acc_str = str(acc_strength)
        acc_str_percentage = ord(acc_str)
        disp = "Found access point:\t" + str(acc_ssid) + "\tStrength:\t" + str(acc_str_percentage)
        print disp

def ChooseAccessPoint(service_name, wifi_dev):
    
    '''
    After looking at the available access points, choose one and activate it
    '''
    
def DisconnectAccessPoint(service_name, wifi_dev_path):
    bus = dbus.SystemBus()
    
    # Need to check device is connected or what. Don't care connected to which AP, do we?
    # ... but for now we assume we know, just for testing purposes
    dev_proxy = bus.get_object(service_name, wifi_dev_path)
    dev_iface = dbus.Interface(dev_proxy, "org.freedesktop.NetworkManager.Device")

#    dev_iface.Disconnect()
    
    print "Device disconnected"

def ConnectAccessPoint(service_name, wifi_dev_path):
    '''

    This function connects the chosen wifi device to the selected Access Point.
    For the purpose of this prototype, we hard code the AP and selected device first.
    There is a little unknown bit where I wasn't able to tell whether a UUID is assigned
    by NM or by this proggy. For now, we make the assumption that it's assigned by us.

    I should probably document all this properly and post it up on a website somewhere.

    '''
    bus = dbus.SystemBus()

    # Generate a random uuid
    identifier = uuid.uuid4()

    s_con = dbus.Dictionary({
            'type': '802-11-wireless',
            'uuid': identifier,
            'id': 'The Connection'})

    s_wifi = dbus.Dictionary({
            'ssid': dbus.ByteArray(ap_ssid),
            'security': '802-11-wireless-security'})

    
def GetConnectionSettings(service_name, accesspoint):
    '''
    Seriously, the lousiness of the NetworkManager documentation is pretty fucking legendary.
    The Python examples given in the source code is a fantastic advertisement on minimalist
    commenting. It is so minimalist as to be non-existent.

    Not to say that this code is all that well-commented, but shit, it's verbose compared to
    those examples.

    Machauhai.
    '''

    bus = dbus.SystemBus()
    ap_proxy = bus.get_object(service_name, accesspoint)
    ap_iface = dbus.Interface(ap_proxy, "org.freedesktop.NetworkManagerSetings.Connection")
    
def ShowActiveAccessPoint(service_name, ap_path):

    ap_properties = dbus.Dictionary()
    connected = int()

    bus = dbus.SystemBus()


    # Need to check is there is an active access point

    # Currently, we're assuming that it's the active one, hey. -- Check state to confirm this, ok
    ''' For the purposes of testing, we're making that assumption. At production we need to be able
    to allow the user to choose which wifi device, if she has more than one. 

    Actually, scratch that. Really need to sort that out nao.

    '''
#    ap_proxy = bus.get_object(service_name, wifi_properties['ActiveAccessPoint'])
    ap_proxy = bus.get_object(service_name, ap_path)

    # Create the interface for the ap
    ap_iface = dbus.Interface(ap_proxy, "org.freedesktop.NetworkManager.AccessPoint" )
    ap_prop_iface = dbus.Interface(ap_proxy, "org.freedesktop.DBus.Properties")

    # Need to specifically say that we want byte_arrays (e.g. string) for the SSID. Who knew?
    try: 
        ap_properties = ap_prop_iface.GetAll("org.freedesktop.NetworkManager.AccessPoint", byte_arrays=True)
        print "\n\n\n"

        for ap in ap_properties:
            datum = str(ap) + ":\t\t" + str(ap_properties[ap])
            print datum
        connected = 1

    except:
        print "Borkiness"
        connected = 0
    
    return connected

if __name__ == '__main__':
    main()
